const BindingX = uni.requireNativePlugin('bindingx');
const dom = uni.requireNativePlugin('dom');
const animation = uni.requireNativePlugin('animation');

export default {
    data() {
        return {}
    },

    watch: {
        show(newVal) {
            if (this.autoClose) return
            if (this.stop) return
            this.stop = true
            if (newVal) {
                this.open(newVal)
            } else {
                this.close()
            }
        },
        leftOptions() {
            this.getSelectorQuery()
            this.init()
        },
        rightOptions(newVal) {
            this.init()
        }
    },
    created() {
        if (this.swipeaction.children !== undefined) {
            this.swipeaction.children.push(this)
        }
    },
    mounted() {
        this.box = this.getEl(this.$refs['selector-box--hock'])
        this.selector = this.getEl(this.$refs['selector-content--hock']);
        this.leftButton = this.getEl(this.$refs['selector-left-button--hock']);
        this.rightButton = this.getEl(this.$refs['selector-right-button--hock']);
        this.init()
    },
    beforeDestroy() {
        this.swipeaction.children.forEach((item, index) => {
            if (item === this) {
                this.swipeaction.children.splice(index, 1)
            }
        })
    },
    methods: {
        init() {
            this.$nextTick(() => {
                this.x = 0
                this.button = {
                    show: false
                }
                setTimeout(() => {
                    this.getSelectorQuery()
                }, 200)
            })
        },
        onClick(index, item, position) {
            this.$emit('click', {
                content: item,
                index,
                position
            })
        },
        touchstart(e) {
            // 每次只触发一次，避免多次监听造成闪烁
            if (this.stop) return
            this.stop = true
            if (this.autoClose) {
                this.swipeaction.closeOther(this)
            }

            const leftWidth = this.button.left.width
            const rightWidth = this.button.right.width
            let expression = this.range(this.x, -rightWidth, leftWidth)
            let leftExpression = this.range(this.x - leftWidth, -leftWidth, 0)
            let rightExpression = this.range(this.x + rightWidth, 0, rightWidth)

            this.eventpan = BindingX.bind({
                anchor: this.box,
                eventType: 'pan',
                props: [{
                    element: this.selector,
                    property: 'transform.translateX',
                    expression
                }, {
                    element: this.leftButton,
                    property: 'transform.translateX',
                    expression: leftExpression
                }, {
                    element: this.rightButton,
                    property: 'transform.translateX',
                    expression: rightExpression
                },]
            }, (e) => {
                // nope
                if (e.state === 'end') {
                    this.x = e.deltaX + this.x;
                    this.isclick = true
                    this.bindTiming(e.deltaX)
                }
            });
        },
        touchend(e) {
            if (this.isopen !== 'none' && !this.isclick) {
                this.open('none')
            }
        },
        bindTiming(x) {
            const left = this.x
            const leftWidth = this.button.left.width
            const rightWidth = this.button.right.width
            const threshold = this.threshold
            if (!this.isopen || this.isopen === 'none') {
                if (left > threshold) {
                    this.open('left')
                } else if (left < -threshold) {
                    this.open('right')
                } else {
                    this.open('none')
                }
            } else {
                if ((x > -leftWidth && x < 0) || x > rightWidth) {
                    if ((x > -threshold && x < 0) || (x - rightWidth > threshold)) {
                        this.open('left')
                    } else {
                        this.open('none')
                    }
                } else {
                    if ((x < threshold && x > 0) || (x + leftWidth < -threshold)) {
                        this.open('right')
                    } else {
                        this.open('none')
                    }
                }
            }
        },

        /**
         * 移动范围
         * @param {Object} num
         * @param {Object} mix
         * @param {Object} max
         */
        range(num, mix, max) {
            return `min(max(x+${num}, ${mix}), ${max})`
        },

        /**
         * 开启swipe
         */
        open(type) {
            this.animation(type)
        },

        /**
         * 关闭swipe
         */
        close() {
            this.animation('none')
        },

        /**
         * 开启关闭动画
         * @param {Object} type
         */
        animation(type) {
            const time = 300
            const leftWidth = this.button.left.width
            const rightWidth = this.button.right.width
            if (this.eventpan && this.eventpan.token) {
                BindingX.unbind({
                    token: this.eventpan.token,
                    eventType: 'pan'
                })
            }

            switch (type) {
                case 'left':
                    Promise.all([
                        this.move(this.selector, leftWidth),
                        this.move(this.leftButton, 0),
                        this.move(this.rightButton, rightWidth * 2)
                    ]).then(() => {
                        this.setEmit(leftWidth, type)
                    })
                    break
                case 'right':
                    Promise.all([
                        this.move(this.selector, -rightWidth),
                        this.move(this.leftButton, -leftWidth * 2),
                        this.move(this.rightButton, 0)
                    ]).then(() => {
                        this.setEmit(-rightWidth, type)
                    })
                    break
                default:
                    Promise.all([
                        this.move(this.selector, 0),
                        this.move(this.leftButton, -leftWidth),
                        this.move(this.rightButton, rightWidth)
                    ]).then(() => {
                        this.setEmit(0, type)
                    })

            }
        },
        setEmit(x, type) {
            const leftWidth = this.button.left.width
            const rightWidth = this.button.right.width
            this.isopen = this.isopen || 'none'
            this.stop = false
            this.isclick = false
            // 只有状态不一致才会返回结果
            if (this.isopen !== type && this.x !== x) {
                if (type === 'left' && leftWidth > 0) {
                    this.$emit('change', 'left')
                }
                if (type === 'right' && rightWidth > 0) {
                    this.$emit('change', 'right')
                }
                if (type === 'none') {
                    this.$emit('change', 'none')
                }
            }
            this.x = x
            this.isopen = type
        },
        move(ref, value) {
            return new Promise((resolve, reject) => {
                animation.transition(ref, {
                    styles: {
                        transform: `translateX(${value})`,
                    },
                    duration: 150, //ms
                    timingFunction: 'linear',
                    needLayout: false,
                    delay: 0 //ms
                }, function (res) {
                    resolve(res)
                })
            })

        },

        /**
         * 获取ref
         * @param {Object} el
         */
        getEl(el) {
            return el.ref
        },
        /**
         * 获取节点信息
         */
        getSelectorQuery() {
            Promise.all([
                this.getDom('left'),
                this.getDom('right'),
            ]).then((data) => {
                let show = 'none'
                if (this.autoClose) {
                    show = 'none'
                } else {
                    show = this.show
                }

                if (show === 'none') {
                    // this.close()
                } else {
                    this.open(show)
                }

            })

        },
        getDom(str) {
            return new Promise((resolve, reject) => {
                dom.getComponentRect(this.$refs[`selector-${str}-button--hock`], (data) => {
                    if (data) {
                        this.button[str] = data.size
                        resolve(data)
                    } else {
                        reject()
                    }
                })
            })
        }
    }
}
